package cn.tedu.lucky.draw.server.aspect;

import cn.tedu.lucky.draw.server.common.annotation.OperationLog;
import cn.tedu.lucky.draw.server.repository.UserLogRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Component
@Aspect
public class LogAspect {

    @Autowired
    private UserLogRepository userLogRepository;


    //定义切入点
    @Pointcut("@annotation(cn.tedu.lucky.draw.server.common.annotation.OperationLog)")
    public void doLog(){}

    //定义通知
    @Around("doLog()")
    public Object doLogAround(ProceedingJoinPoint joinPoint) throws Throwable{
        //执行状态，初始状态
        int status = 1;
        //错误信息
        String error=null;
        //耗时
        long time=0L;

        //开始执行日志处理
        long t1 = System.currentTimeMillis();
        try{
            Object result = joinPoint.proceed();
            long t2 = System.currentTimeMillis();
            time = t2 - t1;
            return result;
        }catch (Throwable e){
            long t3 = System.currentTimeMillis();
            time = t3 - t1;
            status = 0;
            error = e.getMessage();
            throw e;
        }finally {
            //做日志记录
            saveOperationLog(joinPoint,status,error,time);
        }
    }

    private void saveOperationLog(ProceedingJoinPoint joinPoint, int status, String error, long time) throws NoSuchMethodException, JsonProcessingException {
        /**
         * ServletRequestAttributes 是继承自RequestAttributes，添加了一些特定的方法来处理ServletRequest
         * RequestContextHolder 是Spring框架中的一个类，它提供了访问当前请求的上下文的方法
         * getRequestAttributes()会返回当前线程中的请求属性
         * requestAttributes.getRequest();可以获取到当前的WEB请求，以此可以获取其中的查询参数、请求头、会话等信息
         */
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = requestAttributes.getRequest();
        //获取IP地址
        String ip = httpServletRequest.getRemoteAddr();
        //获取用户名
        String username="TEDU";
        //获取类的字节码文件
        Class<?> targetClass = joinPoint.getTarget().getClass();
        //获取方法声明
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        //获取方法
        Method targetMethod = targetClass.getMethod(ms.getName(), ms.getParameterTypes());
        //获取方法上的注解
        OperationLog operationLog = targetMethod.getAnnotation(OperationLog.class);
        //获取方法的操作描述
        String operation = operationLog.operation();
        //获取方法的名称
        String method=targetClass.getName()+"."+targetMethod.getName();
        //获取方法参数
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        String params = objectMapper.writeValueAsString(joinPoint.getArgs());

    }
}
